#  Copyright (c) 2010
#  The Regents of the University of Michigan
#  All Rights Reserved

#  Permission is granted to use, copy, create derivative works, and
#  redistribute this software and such derivative works for any purpose,
#  so long as the name of the University of Michigan is not used in
#  any advertising or publicity pertaining to the use or distribution
#  of this software without specific, written prior authorization. If
#  the above copyright notice or any other identification of the
#  University of Michigan is included in any copy of any portion of
#  this software, then the disclaimer below must also be included.

#  This software is provided as is, without representation or warranty
#  of any kind either express or implied, including without limitation
#  the implied warranties of merchantability, fitness for a particular
#  purpose, or noninfringement.  The Regents of the University of
#  Michigan shall not be liable for any damages, including special,
#  indirect, incidental, or consequential damages, with respect to any
#  claim arising out of or in connection with the use of the software,
#  even if it has been or is hereafter advised of the possibility of
#  such damages.
import collections

rules_list = []

def rule(f):
  rules_list.append(f)
  return f

refine_rules_lists = collections.defaultdict(list)
def refine(*categories):
  '''Indicates that a function refines the type passed as an argument.'''
  def dec(f):
    for category in categories:
      if not isinstance(category, str):
        raise TypeError('refine excepted str, not %s' % type(category))

      # make_wrapper is needed to bind category; otherwise it changes as part
      # of the outer for loop and so it evaluates to the same thing across all
      # wrappers. =(
      def make_wrapper(category): 
        def g(name_tokens, tokens, biggest_extension):
          new_category = f(name_tokens, tokens, biggest_extension)
          if new_category is not None:
            return new_category + category
        return g
      refine_rules_lists[category].append(make_wrapper(category))
    return f
  return dec
